package Core

import (
	"net/http"
	"time"
	"strconv"
	"compress/gzip"
	"encoding/json"
)

// declare HxResponse struct
type HxResponse struct {
	IsDone       bool
	IsGzip       bool
	Body         string
	Status       int
	ContentType  string
	Header map[string]string
	Raw          http.ResponseWriter
}

// Set response cache header
// if ex < 1, set no expire
func (rs *HxResponse) Cache(ex int) {
	if ex <= 0 {
		// set no cache
		rs.Header["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
		rs.Header["Expires"] = "Mon, 26 Jul 1997 05:00:00 GMT"
		rs.Header["Pragma"] = "no-cache"
		return
	}
	// set expire cache
	delete(rs.Header, "Pragma")
	now := time.Now()
	rs.Header["Last-Modified"] = now.Format(time.RFC1123)
	rs.Header["Expires"] = now.Add(time.Second*time.Duration(ex)).Format(time.RFC1123)
	rs.Header["Cache-Control"] = "max-age=" + strconv.Itoa(ex)
}

// Set cookie
func (rs *HxResponse) Cookie(name string, value string, expire int) {
	t := time.Now()
	t = t.Add(time.Duration(expire)*time.Second)
	cookie := &http.Cookie{
		Name:name,
		Value:value,
		Path:"/",
		MaxAge:expire,
		Expires:t,
	}
	http.SetCookie(rs.Raw, cookie)
}

// Do response
func (rs *HxResponse) Do() {
	if rs.IsDone {
		return
	}
	rs.Header["Content-Type"] = rs.ContentType
	for name, value := range rs.Header {
		rs.Raw.Header().Set(name, value)
	}
	// write gzip context
	if rs.IsGzip && len(rs.Body) > 0 {
		rs.Raw.Header().Set("Content-Encoding", "gzip")
		g, _ := gzip.NewWriterLevel(rs.Raw, gzip.BestSpeed)
		defer g.Close()
		rs.Raw.WriteHeader(rs.Status)
		g.Write([]byte(rs.Body))
		rs.IsDone = true
		return
	}
	// write direct context string
	rs.Raw.WriteHeader(rs.Status)
	rs.Raw.Write([]byte(rs.Body))
	rs.IsDone = true
}

// Send out redirect response
func (rs *HxResponse) Redirect(url string) {
	rs.Status = 302
	rs.Header["location"] = url
}

// Send out error response
func (rs *HxResponse) Error(code int, cnt string) {
	rs.Status = code
	rs.Body = cnt
}

// Send out json data response
func (rs *HxResponse) Json(data interface {}) error {
	content, err := json.Marshal(data)
	if err != nil {
		return err
	}
	rs.Header["Content-Type"] = "application/json;charset=UTF-8"
	rs.Body = string(content)
	return nil
}

// Create new *HxResponse
func Response(r http.ResponseWriter) *HxResponse {
	rs := &HxResponse{}
	rs.Raw = r
	rs.Status = 200
	rs.ContentType = "text/html;charset=UTF-8"
	rs.Body = ""
	rs.IsDone = false
	rs.IsGzip = Config.Bool("http.gzip")
	rs.Header = make(map[string]string)
	return rs
}



